package ca.uwo.android.campusmap;

import java.util.HashSet;
import java.util.List;

import android.app.SearchManager;
import android.content.Intent;
import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.BaseColumns;
import android.text.TextUtils;
import android.text.TextUtils.TruncateAt;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.ZoomControls;
import ca.uwo.android.R;
import ca.uwo.android.TransparentPanel;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

public class CampusMap extends MapActivity{
	
	private static final String TAG_NAME = "CampusMap";
	
	
	// Data
	private MapView mapView;
	private MapController mapControl;
	private TextView buildlingName;
	private TextView buildlingAddress;
	private LinearLayout messageLayer;
	private LinearLayout mylocStatusPanel;
	private TextView mylocStatus;

	HashSet<Integer> overlayList = new HashSet<Integer>();

	List<Overlay> mapOverlays;
	Drawable destDrawable;
	CampusMapOverlay campusMapOverlay;
	FixedMyLocationOverlay myLocationOverlay;
	boolean myLocationOn;
	GeoPoint buildingPoint;
	

	private void init() {
		myLocationOn = false;

		mapControl.setZoom(16);
		mapControl.setCenter(new GeoPoint(43007363, -81274028));

		myLocationOverlay.disableMyLocation();
		mapOverlays.clear();

		campusMapOverlay.clear();
		messageLayer.setVisibility(View.INVISIBLE);
		mylocStatusPanel.setVisibility(View.INVISIBLE);
		mapView.invalidate();

		overlayList.clear();
		buildingPoint = null;
	}

	final Handler buildlingSelected = new Handler() {
		public void handleMessage(Message msg) {
			if(msg != null) {
				int value = msg.what;
				OverlayItem item = campusMapOverlay.getItem(value);
				buildlingName.setText(item.getTitle());
				buildlingAddress.setText(item.getSnippet());
				autoHideBuildingName();

				buildingPoint = item.getPoint();
			}
		}
	};

	final Handler autohideHandlerLocationMessage = new Handler() {
		int visibleCounter = 0;

		public void handleMessage (Message msg) {
			if(msg != null) {
				if(msg.what == View.VISIBLE)
					visibleCounter++;
				else
					visibleCounter--;

				if(visibleCounter > 0)
					mylocStatusPanel.setVisibility(View.VISIBLE);
				else
					mylocStatusPanel.setVisibility(View.INVISIBLE);
			}
		}
	};

	private void autoHideLocationMessage() {
		new Thread(new Runnable() {
			public void run() {
				autohideHandlerLocationMessage.sendEmptyMessage(View.VISIBLE);
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				autohideHandlerLocationMessage.sendEmptyMessage(View.INVISIBLE);
			}
		}).start();
	}

	final Handler autohideHandlerBuildingName = new Handler() {
		int visibleCounter = 0;

		public void handleMessage (Message msg) {
			if(msg != null) {
				if(msg.what == View.VISIBLE)
					visibleCounter++;
				else
					visibleCounter--;

				if(visibleCounter > 0)
					messageLayer.setVisibility(View.VISIBLE);
				else
					messageLayer.setVisibility(View.INVISIBLE);
			}
		}
	};

	private void autoHideBuildingName() {
		new Thread(new Runnable() {
			public void run() {
				autohideHandlerBuildingName.sendEmptyMessage(View.VISIBLE);
				try {
					Thread.sleep(5000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				autohideHandlerBuildingName.sendEmptyMessage(View.INVISIBLE);
			}
		}).start();
	}

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
				
		
		
//		Log.i(TAG_NAME, "in onCreate of CampusMap");
		setContentView(R.layout.campus_map);
		setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL); 

		handleIntent(getIntent());


		mapView = (MapView) findViewById(R.id.cmCampusGoogleMap);
		TextView title = (TextView)findViewById(R.id.moduleName);
		messageLayer = (TransparentPanel)findViewById(R.id.transparent_panel);

		mylocStatusPanel = (TransparentPanel)findViewById(R.id.mylocation_status_panel);
		mylocStatus = (TextView)findViewById(R.id.mylocation_status);
		buildlingName = (TextView)findViewById(R.id.map_buildling);

		mapOverlays = mapView.getOverlays();
		destDrawable = this.getResources().getDrawable(R.drawable.ic_maps_indicator_target_position_anim2);
		campusMapOverlay = new CampusMapOverlay(destDrawable, buildlingSelected );

		mapControl = mapView.getController();

		myLocationOverlay = new FixedMyLocationOverlay(this, mapView);

		title.setText("Campus Map");
		title.setSingleLine();
		title.setEllipsize(TextUtils.TruncateAt.MARQUEE);

		buildlingName.setEllipsize(TruncateAt.END);
		buildlingName.setSelected(true);
		buildlingName.setSingleLine();

		buildlingAddress = (TextView)findViewById(R.id.map_address);
		buildlingAddress.setEllipsize(TruncateAt.MARQUEE);
		buildlingAddress.setSelected(true);
		buildlingAddress.setSingleLine();

		// Always show Zoom controls
		ZoomControls zoomControls = (ZoomControls)findViewById(R.id.zoomcontrols);
		zoomControls.setOnZoomInClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				mapControl.zoomIn();
			}
		});
		zoomControls.setOnZoomOutClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				mapControl.zoomOut();
			}
		});


		// Search Button
		((ImageButton)findViewById(R.id.searchButton)).setOnClickListener(new OnClickListener() {			
			@Override
			public void onClick(View v) {
				onSearchClicked();
			}
		});

		// Refresh Button
		((ImageButton)findViewById(R.id.map_refresh)).setOnClickListener(new OnClickListener() {			
			@Override
			public void onClick(View v) {
				init();
			}
		});

		// Go to place Button
		((ImageButton)findViewById(R.id.map_destination)).setOnClickListener(new OnClickListener() {			
			@Override
			public void onClick(View v) {
				if(buildingPoint != null) {
					mapControl.setCenter(buildingPoint);
					autoHideBuildingName();
				}
			}
		});



		((ImageButton)findViewById(R.id.my_location)).setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if(myLocationOverlay.isMyLocationEnabled()) {
					GeoPoint me = myLocationOverlay.getMyLocation();		
					if(me != null) {
						mapControl.setCenter(me);						
					}
					else {
						if(myLocationOverlay.getLastFix() != null)
							showAlert("Location information temporarily unavailable");
						else
							showAlert("Searching for your location, please wait");						
					}
				}
				else {
					boolean success = myLocationOverlay.enableMyLocation();
					if(!success) {
						showAlert("No Location Information Available. Please check your location source setting, or try again later");
					}
					else {
						myLocationOn = true;
						mapOverlays.add(myLocationOverlay);
						GeoPoint me = myLocationOverlay.getMyLocation();		
						if(me != null) {
							mapControl.setCenter(me);						
						}
						else {
							showAlert("Start searching for your location, please wait");													
						}
					}
				}
			}
		});	

		init();
	}
	
	/**
	 * Handle configuration changes ourselves.
	 * Implementing this method and adding android:configChanges="keyboardHidden|orientation"
	 * to the manifest for this activity means that the onCreate method will not be
	 * called every time a user rotates their phone.
	 */
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
	}


	protected void showAlert(String msg) {
		mylocStatus.setText(msg);
		autoHideLocationMessage();
	}

	protected void onSearchClicked() {
		onSearchRequested();
	}

	@Override
	public void onNewIntent(Intent intent) {
		setIntent(intent);
		handleIntent(intent);
	}

	private void handleIntent(Intent intent) {
		if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
			// Search Query Entered
			String query = intent.getStringExtra(SearchManager.QUERY);
			Cursor cursor = managedQuery(BuildingContentProvider.CONTEN_URI, null, null, new String[] {query}, null);
			
			// Let the parent activity manage the cursor lifecycle
			startManagingCursor(cursor);
			drawOverlays(cursor);
		}
		else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
			// Suggestion Selected
			Cursor cursor = managedQuery(intent.getData(), null, null, null, null);
			startManagingCursor(cursor);
			drawOverlays(cursor);
		}
	}

	protected void drawOverlays(Cursor cursor) {
		if(cursor != null) {
			cursor.moveToFirst();

			int nameIndex = cursor.getColumnIndexOrThrow(BuildingDatabase.BUILDING_NAME);
			int addressIndex = cursor.getColumnIndexOrThrow(BuildingDatabase.ADDRESS);
			int idIndex = cursor.getColumnIndexOrThrow(BaseColumns._ID);
			Integer id = cursor.getInt(idIndex);

			String name = cursor.getString(nameIndex);
			String address = cursor.getString(addressIndex);

			if(!overlayList.contains(id)) {
				int latitudeIndex = cursor.getColumnIndexOrThrow(BuildingDatabase.LATITUDE);
				int longitudeIndex = cursor.getColumnIndexOrThrow(BuildingDatabase.LONGITUDE);

				String latitudeString = cursor.getString(latitudeIndex);
				String longitudeString = cursor.getString(longitudeIndex);
				Double latitudeDouble = Double.parseDouble(latitudeString) * 1e6;
				Double longitudeDouble = Double.parseDouble(longitudeString) * 1e6;
				int latitude = latitudeDouble.intValue();
				int longitude = longitudeDouble.intValue();

				overlayList.add(id);

				buildingPoint = new GeoPoint(latitude, longitude);
				mapControl.setCenter(buildingPoint);
				OverlayItem overlayItem = new OverlayItem(buildingPoint, name, address);

				//			campusMapOverlay.clear();
				campusMapOverlay.addOverlays(overlayItem);
				mapOverlays.add(campusMapOverlay);
			}
			buildlingName.setText(name);
			buildlingAddress.setText(address);
			autoHideBuildingName();

			mapView.invalidate();
			mapView.setSelected(true);
		}
	}

	@Override
	protected void onResume() {
		super.onResume();
		// when our activity resumes, we want to register for location updates
		if(myLocationOn)
			myLocationOverlay.enableMyLocation();
	}

	@Override
	protected void onPause() {
		super.onPause();
		// when our activity pauses, we want to remove listening for location updates
		if(myLocationOn)
			myLocationOverlay.disableMyLocation();
	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	
	// TODO remove these methods from here and get them 
	// inherited from BaseMenuActivity as this is duplicate code!
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.main_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {

//		Log.i(TAG_NAME, "Got menu option " + item.getItemId());
		// Handle item selection
		switch (item.getItemId()) {
		case R.id.menu_info_item: {
//			Log.i(TAG_NAME, "Got info menu option");
			Intent browser = new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.info_url)));
			startActivity(browser);
			return true;
		}
		case R.id.menu_help_item: {
//			Log.i(TAG_NAME, "Got help menu option");
			showWebPage(getString(R.string.help_url));
			return true;
		}
		default:
			return super.onOptionsItemSelected(item);
		}
	}

	
	
	public void showWebPage(String url) {
		Intent openHelpPage = new Intent(CampusMap.this,
				ca.uwo.android.ViewWebPage.class);
		openHelpPage.putExtra("URL", url);
		startActivity(openHelpPage);
	}
	
	
}
